home *** CD-ROM | disk | FTP | other *** search
- /* ----------------------------------------------------------------
- * FILE
- * ex_tuples.c
- *
- * DESCRIPTION
- * Routines dealing with the executor tuple tables. These
- * are used to ensure that the executor frees copies of tuples
- * (made by ExecTargetList) properly.
- *
- * Routines dealing with the type inforamtion for tuples.
- * Currently, the type information for a tuple is an array of
- * struct attribute. This information is needed by routines
- * manipulating tuples (getattribute, formtuple, etc.).
- *
- * INTERFACE ROUTINES
- *
- * TABLE CREATE/DELETE
- * ExecCreateTupleTable - create a new tuple table
- * ExecDestroyTupleTable - destroy a table
- *
- * SLOT RESERVERATION
- * ExecAllocTableSlot - find an available slot in the table
- * ExecGetTableSlot - get a slot corresponding to a table index
- *
- * SLOT ACCESSORS
- * ExecStoreTuple - store a tuple in the table
- * ExecFetchTuple - fetch a tuple from the table
- * ExecClearTuple - clear contents of a table slot
- * ExecSlotPolicy - return slot's tuple pfree policy
- * ExecSetSlotPolicy - diddle the slot policy
- * ExecSlotDescriptor - type of tuple in a slot
- * ExecSetSlotDescriptor - set a slot's tuple descriptor
- * ExecSetSlotDescriptorIsNew - diddle the slot-desc-is-new flag
- * ExecSetNewSlotDescriptor - set a desc and the is-new-flag all at once
- * ExecSlotBuffer - return buffer of tuple in slot
- * ExecSetSlotBuffer - set the buffer for tuple in slot
- * ExecIncrSlotBufferRefcnt - bump the refcnt of the slot buffer
- *
- * SLOT STATUS PREDICATES
- * ExecNullSlot - true when slot contains no tuple
- * ExecSlotDescriptorIsNew - true if we're now storing a different
- * type of tuple in a slot
- *
- * CONVENIENCE INITIALIZATION ROUTINES
- * ExecInitResultTupleSlot \ convience routines to initialize
- * ExecInitScanTupleSlot \ the various tuple slots for nodes
- * ExecInitRawTupleSlot \ which store copies of tuples.
- * ExecInitMarkedTupleSlot /
- * ExecInitOuterTupleSlot /
- * ExecInitHashTupleSlot /
- *
- * old routines:
- * ExecGetTupType - get type of tuple returned by this node
- * ExecTypeFromTL - form a TupleDescriptor from a target list
- *
- * EXAMPLE OF HOW TABLE ROUTINES WORK
- * Suppose we have a query such as retrieve (EMP.name) and we have
- * a single SeqScan node in the query plan.
- *
- * At ExecMain(EXEC_START)
- * ----------------
- * - InitPlan() calls ExecCreateTupleTable() to create the tuple
- * table which will hold tuples processed by the executor.
- *
- * - ExecInitSeqScan() calls ExecInitScanTupleSlot() and
- * ExecInitResultTupleSlot() to reserve places in the tuple
- * table for the tuples returned by the access methods and the
- * tuples resulting from preforming target list projections.
- *
- * During ExecMain(EXEC_RUN)
- * ----------------
- * - SeqNext() calls ExecStoreTuple() to place the tuple returned
- * by the access methods into the scan tuple slot.
- *
- * - ExecProcSeqScan() calls ExecStoreTuple() to take the result
- * tuple from ExecTargetList() and place it into the result tuple
- * slot.
- *
- * - ExecutePlan() calls ExecRetrieve() which gets the tuple out of
- * the slot passed to it by calling ExecFetchTuple(). this tuple
- * is then returned.
- *
- * At ExecMain(EXEC_END)
- * ----------------
- * - EndPlan() calls ExecDestroyTupleTable() to clean up any remaining
- * tuples left over from executing the query.
- *
- * The important thing to watch in the executor code is how pointers
- * to the slots containing tuples are passed instead of the tuples
- * themselves. This facilitates the communication of related information
- * (such as whether or not a tuple should be pfreed, what buffer contains
- * this tuple, the tuple's tuple descriptor, etc). Note that much of
- * this information is also kept in the ExprContext of each node.
- * Soon the executor will be redesigned and ExprContext's will contain
- * only slot pointers. -cim 3/14/91
- *
- * NOTES
- * The tuple table stuff is relatively new, put here to alleviate
- * the process growth problems in the executor. The other routines
- * are old (from the original lisp system) and may someday become
- * obsolete. -cim 6/23/90
- *
- * In the implementation of nested-dot queries such as
- * "retrieve (EMP.hobbies.all)", a single scan may return tuples
- * of many types, so now we return pointers to tuple descriptors
- * along with tuples returned via the tuple table. This means
- * we now have a bunch of routines to diddle the slot descriptors
- * too. -cim 1/18/90
- *
- * The tuple table stuff depends on the lib/H/executor/tuptable.h macros,
- * and the TupleTableSlot node in execnodes.h.
- *
- * IDENTIFICATION
- * $Header: /private/postgres/src/executor/RCS/ex_tuples.c,v 1.17 1992/08/04 17:37:46 mer Exp $
- * ----------------------------------------------------------------
- */
-
- #include "executor/executor.h"
- #undef ExecStoreTuple
-
- RcsId("$Header: /private/postgres/src/executor/RCS/ex_tuples.c,v 1.17 1992/08/04 17:37:46 mer Exp $");
-
- /* ----------------------------------------------------------------
- * tuple table create/delete functions
- * ----------------------------------------------------------------
- */
- /* --------------------------------
- * ExecCreateTupleTable
- *
- * This creates a new tuple table of the specified initial
- * size. If the size is insufficient, ExecAllocTableSlot()
- * will grow the table as necessary.
- *
- * This should be used by InitPlan() to allocate the table.
- * The table's address would then be stored somewhere
- * in the EState structure.
- * --------------------------------
- */
- TupleTable /* return: address of table */
- ExecCreateTupleTable(initialSize)
- int initialSize; /* initial number of slots in table */
- {
- TupleTable newtable; /* newly allocated table */
- Pointer array; /* newly allocated table array */
-
- /* ----------------
- * sanity checks
- * ----------------
- */
- Assert(initialSize >= 1);
-
- /* ----------------
- * Now allocate our new table along with space for the pointers
- * to the tuples. Note: our array is actually an array of
- * TupleTableCells (which is a subclass of LispValue).
- * This is for 2 reasons: 1) there's lots of code that expects
- * tuples to be returned "inside" lispCons cells and 2) the cdr
- * field may one day be useful.
- * -cim 6/23/90
- * ----------------
- */
- newtable = (TupleTable) palloc(sizeof(TupleTableData));
- array = (Pointer) palloc(initialSize * TableSlotSize);
-
- /* ----------------
- * clean out the slots we just allocated
- * ----------------
- */
- bzero(array, initialSize * TableSlotSize);
-
- /* ----------------
- * initialize the new table and return it to the caller.
- * ----------------
- */
- newtable->size = initialSize;
- newtable->next = 0;
- newtable->array = array;
-
- return newtable;
- }
-
- /* --------------------------------
- * ExecDestroyTupleTable
- *
- * This pfrees the storage assigned to the tuple table and
- * optionally pfrees the contents of the table also.
- * It is expected that this routine be called by EndPlan().
- * --------------------------------
- */
- void
- ExecDestroyTupleTable(table, shouldFree)
- TupleTable table; /* tuple table */
- bool shouldFree; /* true if we should free slot contents */
- {
- int next; /* next avaliable slot */
- Pointer array; /* start of table array */
- int i; /* counter */
-
- /* ----------------
- * sanity checks
- * ----------------
- */
- Assert(table != NULL);
-
- /* ----------------
- * get information from the table
- * ----------------
- */
- array = table->array;
- next = table->next;
-
- /* ----------------
- * first free all the valid pointers in the tuple array
- * if that's what the caller wants..
- *
- * Note: we do nothing about the Buffer and Tuple Descriptor's
- * we store in the slots. This may have to change (ex: we should
- * probably worry about pfreeing tuple descs too) -cim 3/14/91
- * ----------------
- */
- if (shouldFree)
- for (i = 0; i < next; i++) {
- Pointer slot;
- Pointer tuple;
-
- slot = TableSlot(array, i);
- tuple = SlotContents(slot);
-
- if (tuple != NULL) {
- SetSlotContents(slot, NULL);
- if (SlotShouldFree((TupleTableSlot) slot)) {
- /* ----------------
- * since a tuple may contain a pointer to
- * lock information allocated along with the
- * tuple, we have to be careful to free any
- * rule locks also -cim 1/17/90
- * ----------------
- */
- HeapTupleFreeRuleLock(tuple);
- pfree(tuple);
- }
- }
- }
-
- /* ----------------
- * finally free the tuple array and the table itself.
- * ----------------
- */
- pfree(array);
- pfree(table);
-
- }
-
-
- /* ----------------------------------------------------------------
- * tuple table slot reservation functions
- * ----------------------------------------------------------------
- */
- /* --------------------------------
- * ExecAllocTableSlot
- *
- * This routine is used to reserve slots in the table for
- * use by the various plan nodes. It is expected to be
- * called by the node init routines (ex: ExecInitNestLoop).
- * once per slot needed by the node. Not all nodes need
- * slots (some just pass tuples around).
- * --------------------------------
- */
- int /* return: index into tuple table */
- ExecAllocTableSlot(table)
- TupleTable table; /* tuple table */
- {
- int slotnum; /* new slot number (returned) */
-
- /* ----------------
- * sanity checks
- * ----------------
- */
- Assert(table != NULL);
-
- /* ----------------
- * if our table is full we have to allocate a larger
- * size table. Since ExecAllocTableSlot() is only called
- * before the table is ever used to store tuples, we don't
- * have to worry about the contents of the old table.
- * If this changes, then we will have to preserve the contents.
- * -cim 6/23/90
- *
- * Unfortunately, we *cannot* do this. All of the nodes in
- * the plan that have already initialized their slots will have
- * pointers into _freed_ memory. This leads to bad ends. We
- * now count the number of slots we will need and create all the
- * slots we will need ahead of time. The if below should never
- * happen now. Give a WARN if it does. -mer 4 Aug 1992
- * ----------------
- */
- if (table->next >= table->size) {
- /*
- * int newsize = NewTableSize(table->size);
- *
- * pfree(table->array);
- * table->array = (Pointer) palloc(newsize * TableSlotSize);
- * bzero(table->array, newsize * TableSlotSize);
- * table->size = newsize;
- */
- elog(NOTICE, "Plan requires more slots than are available");
- elog(WARN, "send mail to your local executor guru to fix this");
- }
-
- /* ----------------
- * at this point, space in the table is guaranteed so we
- * reserve the next slot, initialize and return it.
- * ----------------
- */
- slotnum = table->next;
- table->next++;
-
- InitSlot(ExecGetTableSlot(table, slotnum));
- return slotnum;
- }
-
- /* --------------------------------
- * ExecGetTableSlot
- *
- * This routine is used to get the slot (an address) corresponding
- * to a slot number (an index) for the specified tuple table.
- * --------------------------------
- */
- Pointer /* return: address of slot containing tuple */
- ExecGetTableSlot(table, slotnum)
- TupleTable table; /* table */
- int slotnum; /* number of slot */
- {
- Pointer slot; /* slot corresponding to slotnum in table */
-
- /* ----------------
- * sanity checks
- * ----------------
- */
- Assert(table != NULL);
- Assert(slotnum >= 0 && slotnum < table->next);
-
- /* ----------------
- * get information from the tuple table and return it.
- * ----------------
- */
- slot = TableSlot(table->array, slotnum);
-
- return slot;
- }
-
- /* ----------------------------------------------------------------
- * tuple table slot accessor functions
- * ----------------------------------------------------------------
- */
-
- /* --------------------------------
- * ExecStoreTuple
- *
- * This function is used to store a tuple into a specified
- * slot in the tuple table. Note: the only slots which should
- * be called with shouldFree == false are those slots used to
- * store tuples not allocated with pfree(). Currently the
- * seqscan and indexscan nodes use this for the tuples returned
- * by amgetattr, which are actually pointers onto disk pages.
- * --------------------------------
- */
- Pointer /* return: slot passed */
- ExecStoreTuple(tuple, slot, buffer, shouldFree)
- Pointer tuple; /* tuple to store */
- Pointer slot; /* slot in which to store tuple */
- Buffer buffer; /* buffer associated with tuple */
- bool shouldFree; /* true if we call pfree() when we gc. */
- {
- Pointer oldtuple; /* prior contents of slot */
-
- /* ----------------
- * sanity checks
- * ----------------
- */
- Assert(slot != NULL);
-
- /* ----------------
- * get information from the tuple table
- * ----------------
- */
- oldtuple = SlotContents(slot);
-
- /* ----------------
- * free the old contents of the specified slot if necessary.
- * ----------------
- */
- if (SlotShouldFree((TupleTableSlot) slot) && oldtuple != NULL) {
- /* ----------------
- * since a tuple may contain a pointer to
- * lock information allocated along with the
- * tuple, we have to be careful to free any
- * rule locks also -cim 1/17/90
- * ----------------
- */
- HeapTupleFreeRuleLock(oldtuple);
- pfree(oldtuple);
- }
-
- /* ----------------
- * if we have a buffer pinned, release it before stomping on it.
- * ----------------
- */
- if (BufferIsValid(SlotBuffer((TupleTableSlot) slot)))
- ReleaseBuffer(SlotBuffer((TupleTableSlot) slot));
-
- /* ----------------
- * store the new tuple into the specified slot and
- * return the slot into which we stored the tuple.
- * ----------------
- */
- SetSlotContents((TupleTableSlot) slot, tuple);
- SetSlotBuffer((TupleTableSlot) slot, buffer);
- SetSlotShouldFree((TupleTableSlot) slot, shouldFree);
-
- return slot;
- }
-
- Pointer /* return: slot passed */
- ExecStoreTupleDebug(file, line, tuple, slot, buffer, shouldFree)
- String file; /* filename */
- int line; /* line number */
- Pointer tuple; /* tuple to store */
- Pointer slot; /* slot in which to store tuple */
- Buffer buffer; /* buffer associated with tuple */
- bool shouldFree; /* true if we call pfree() when we gc. */
- {
- printf(":EST f %s l %d t 0x%x s 0x%x b %d sf %d\n",
- file, line, tuple, slot, buffer, shouldFree);
- return
- ExecStoreTuple(tuple, slot, buffer, shouldFree);
- }
-
- /* --------------------------------
- * ExecFetchTuple
- *
- * This function is used to get the heap tuple out of
- * a slot in the tuple table.
- * --------------------------------
- *
- * Now a macro in tuptable.h -mer 5 March 1992
- */
-
- /* --------------------------------
- * ExecClearTuple
- *
- * This function is used to clear out a slot in the tuple table.
- * --------------------------------
- */
- Pointer /* return: slot passed */
- ExecClearTuple(slot)
- Pointer slot; /* slot in which to store tuple */
- {
- Pointer oldtuple; /* prior contents of slot */
-
- /* ----------------
- * sanity checks
- * ----------------
- */
- Assert(slot != NULL);
-
- /* ----------------
- * get information from the tuple table
- * ----------------
- */
- oldtuple = SlotContents(slot);
-
- /* ----------------
- * free the old contents of the specified slot if necessary.
- * ----------------
- */
- if (SlotShouldFree((TupleTableSlot) slot) && oldtuple != NULL) {
- /* ----------------
- * since a tuple may contain a pointer to
- * lock information allocated along with the
- * tuple, we have to be careful to free any
- * rule locks also -cim 1/17/90
- * ----------------
- */
- HeapTupleFreeRuleLock(oldtuple);
- pfree(oldtuple);
- }
-
- /* ----------------
- * store NULL into the specified slot and return the slot.
- * - also set buffer to InvalidBuffer -cim 3/14/91
- * ----------------
- */
- SetSlotContents(slot, NULL);
-
- if (BufferIsValid(SlotBuffer((TupleTableSlot) slot)))
- ReleaseBuffer(SlotBuffer((TupleTableSlot) slot));
-
- SetSlotBuffer((TupleTableSlot) slot, InvalidBuffer);
- SetSlotShouldFree((TupleTableSlot) slot, true);
-
- return slot;
- }
-
-
- /* --------------------------------
- * ExecSlotPolicy
- *
- * This function is used to get the call/don't call pfree
- * setting of a slot. Most executor routines don't need this.
- * It's only when you do tricky things like marking tuples for
- * merge joins that you need to diddle the slot policy.
- * --------------------------------
- */
- bool /* return: slot policy */
- ExecSlotPolicy(slot)
- Pointer slot; /* slot to inspect */
- {
- bool shouldFree = SlotShouldFree((TupleTableSlot) slot);
- return shouldFree;
- }
-
- /* --------------------------------
- * ExecSetSlotPolicy
- *
- * This function is used to change the call/don't call pfree
- * setting of a slot. Most executor routines don't need this.
- * It's only when you do tricky things like marking tuples for
- * merge joins that you need to diddle the slot policy.
- * --------------------------------
- */
- bool /* return: old slot policy */
- ExecSetSlotPolicy(slot, shouldFree)
- Pointer slot; /* slot to change */
- bool shouldFree; /* true if we call pfree() when we gc. */
- {
- bool old_shouldFree = SlotShouldFree((TupleTableSlot) slot);
- SetSlotShouldFree((TupleTableSlot) slot, shouldFree);
-
- return old_shouldFree;
- }
-
- /* --------------------------------
- * ExecSlotDescriptor
- *
- * This function is used to get the tuple descriptor associated
- * with the slot's tuple.
- *
- * Now a macro in tuptable.h -mer 5 March 1992
- * --------------------------------
- */
-
- /* --------------------------------
- * ExecSetSlotDescriptor
- *
- * This function is used to set the tuple descriptor associated
- * with the slot's tuple.
- * --------------------------------
- */
- TupleDescriptor /* return: old slot tuple descriptor */
- ExecSetSlotDescriptor(slot, tupdesc)
- Pointer slot; /* slot to change */
- TupleDescriptor tupdesc; /* tuple descriptor */
- {
- TupleDescriptor old_tupdesc = SlotTupleDescriptor((TupleTableSlot) slot);
- SetSlotTupleDescriptor((TupleTableSlot) slot, tupdesc);
-
- return old_tupdesc;
- }
-
- /* --------------------------------
- * ExecSetSlotDescriptorIsNew
- *
- * This function is used to change the setting of the "isNew" flag
- * --------------------------------
- */
- void
- ExecSetSlotDescriptorIsNew(slot, isNew)
- Pointer slot; /* slot to change */
- bool isNew; /* "isNew" setting */
- {
- SetSlotTupleDescriptorIsNew((TupleTableSlot) slot, isNew);
- }
-
- /* --------------------------------
- * ExecSetNewSlotDescriptor
- *
- * This function is used to set the tuple descriptor associated
- * with the slot's tuple, and set the "isNew" flag at the same time.
- * --------------------------------
- */
- TupleDescriptor /* return: old slot tuple descriptor */
- ExecSetNewSlotDescriptor(slot, tupdesc)
- Pointer slot; /* slot to change */
- TupleDescriptor tupdesc; /* tuple descriptor */
- {
- TupleDescriptor old_tupdesc = SlotTupleDescriptor((TupleTableSlot) slot);
- SetSlotTupleDescriptor((TupleTableSlot) slot, tupdesc);
- SetSlotTupleDescriptorIsNew((TupleTableSlot) slot, true);
-
- return old_tupdesc;
- }
-
- /* --------------------------------
- * ExecSlotBuffer
- *
- * This function is used to get the tuple descriptor associated
- * with the slot's tuple. Be very careful with this as it does not
- * balance the reference counts. If the buffer returned is stored
- * someplace else, then also use ExecIncrSlotBufferRefcnt().
- *
- * Now a macro in tuptable.h
- * --------------------------------
- */
-
- /* --------------------------------
- * ExecSetSlotBuffer
- *
- * This function is used to set the tuple descriptor associated
- * with the slot's tuple. Be very careful with this as it does not
- * balance the reference counts. If we're using this then we should
- * also use ExecIncrSlotBufferRefcnt().
- * --------------------------------
- */
- Buffer /* return: old slot buffer */
- ExecSetSlotBuffer(slot, b)
- Pointer slot; /* slot to change */
- Buffer b; /* tuple descriptor */
- {
- Buffer oldb = SlotBuffer((TupleTableSlot) slot);
- SetSlotBuffer((TupleTableSlot) slot, b);
-
- return oldb;
- }
-
- /* --------------------------------
- * ExecIncrSlotBufferRefcnt
- *
- * When we pass around buffers in the tuple table, we have to
- * be careful to increment reference counts appropriately.
- * This is used mainly in the mergejoin code.
- * --------------------------------
- */
- void
- ExecIncrSlotBufferRefcnt(slot)
- Pointer slot; /* slot to bump refcnt */
- {
- Buffer b = SlotBuffer((TupleTableSlot) slot);
- if (BufferIsValid(b))
- IncrBufferRefCount(b);
- }
-
- /* ----------------------------------------------------------------
- * tuple table slot status predicates
- * ----------------------------------------------------------------
- */
-
- /* ----------------
- * ExecNullSlot
- *
- * This is used mainly to detect when there are no more
- * tuples to process. The TupIsNull() macro calls this.
- * ----------------
- */
- bool /* return: true if tuple in slot is NULL */
- ExecNullSlot(slot)
- Pointer slot; /* slot to check */
- {
- Pointer tuple; /* contents of slot (returned) */
-
- /* ----------------
- * if the slot itself is null then we return true
- * ----------------
- */
- if (slot == NULL)
- return true;
-
- /* ----------------
- * get information from the slot and return true or
- * false depending on the contents of the slot.
- * ----------------
- */
- tuple = SlotContents(slot);
-
- return
- (tuple == NULL ? true : false);
- }
-
- /* --------------------------------
- * ExecSlotDescriptorIsNew
- *
- * This function is used to check if the tuple descriptor
- * associated with this slot has just changed. ie: we are
- * now storing a new type of tuple in this slot
- * --------------------------------
- */
- bool /* return: descriptor "is new" */
- ExecSlotDescriptorIsNew(slot)
- Pointer slot; /* slot to inspect */
- {
- bool isNew = SlotTupleDescriptorIsNew((TupleTableSlot) slot);
- return isNew;
- }
-
- /* ----------------------------------------------------------------
- * convenience initialization routines
- * ----------------------------------------------------------------
- */
- /* --------------------------------
- * ExecInit{Result,Scan,Raw,Marked,Outer,Hash}TupleSlot
- *
- * These are convience routines to initialize the specfied slot
- * in nodes inheriting the appropriate state.
- * --------------------------------
- */
- #define INIT_SLOT_DEFS \
- TupleTable tupleTable; \
- int slotnum; \
- Pointer slot
-
- #define INIT_SLOT_ALLOC \
- tupleTable = (TupleTable) get_es_tupleTable(estate); \
- slotnum = ExecAllocTableSlot(tupleTable); \
- slot = ExecGetTableSlot(tupleTable, slotnum); \
- SetSlotContents((TupleTableSlot) slot, NULL); \
- SetSlotShouldFree((TupleTableSlot) slot, true); \
- SetSlotTupleDescriptor((TupleTableSlot) slot, (TupleDescriptor) NULL); \
- SetSlotExecTupDescriptor((TupleTableSlot) slot, (ExecTupDescriptor) NULL); \
- SetSlotWhichPlan((TupleTableSlot) slot, -1); \
- SetSlotTupleDescriptorIsNew((TupleTableSlot) slot, true)
-
- /* ----------------
- * ExecInitResultTupleSlot
- * ----------------
- */
- void
- ExecInitResultTupleSlot(estate, commonstate)
- EState estate;
- CommonState commonstate;
- {
- INIT_SLOT_DEFS;
- INIT_SLOT_ALLOC;
- set_cs_ResultTupleSlot(commonstate, (TupleTableSlot) slot);
- }
-
- /* ----------------
- * ExecInitScanTupleSlot
- * ----------------
- */
- void
- ExecInitScanTupleSlot(estate, commonscanstate)
- EState estate;
- CommonScanState commonscanstate;
- {
- INIT_SLOT_DEFS;
- INIT_SLOT_ALLOC;
- set_css_ScanTupleSlot(commonscanstate, (TupleTableSlot)slot);
- }
-
- /* ----------------
- * ExecInitRawTupleSlot
- * ----------------
- */
- void
- ExecInitRawTupleSlot(estate, commonscanstate)
- EState estate;
- CommonScanState commonscanstate;
- {
- INIT_SLOT_DEFS;
- INIT_SLOT_ALLOC;
- set_css_RawTupleSlot(commonscanstate, (TupleTableSlot)slot);
- }
-
- /* ----------------
- * ExecInitMarkedTupleSlot
- * ----------------
- */
- void
- ExecInitMarkedTupleSlot(estate, mergestate)
- EState estate;
- MergeJoinState mergestate;
- {
- INIT_SLOT_DEFS;
- INIT_SLOT_ALLOC;
- set_mj_MarkedTupleSlot(mergestate, (TupleTableSlot) slot);
- }
-
- /* ----------------
- * ExecInitOuterTupleSlot
- * ----------------
- */
- void
- ExecInitOuterTupleSlot(estate, hashstate)
- EState estate;
- HashJoinState hashstate;
- {
- INIT_SLOT_DEFS;
- INIT_SLOT_ALLOC;
- set_hj_OuterTupleSlot(hashstate, slot);
- }
-
- /* ----------------
- * ExecInitHashTupleSlot
- * ----------------
- */
- void
- ExecInitHashTupleSlot(estate, hashstate)
- EState estate;
- HashJoinState hashstate;
- {
- INIT_SLOT_DEFS;
- INIT_SLOT_ALLOC;
- set_hj_HashTupleSlot(hashstate, slot);
- }
-
- TupleTableSlot
- NodeGetResultTupleSlot(node)
- Plan node;
- {
- TupleTableSlot slot;
- union {
- ResultState resstate;
- ScanState scanstate;
- NestLoopState nlstate;
- MaterialState matstate;
- SortState sortstate;
- AggState aggstate;
- HashState hashstate;
- UniqueState uniquestate;
- MergeJoinState mergestate;
- HashJoinState hashjoinstate;
- ScanTempState scantempstate;
- } s;
-
- switch(NodeType(node)) {
-
- case classTag(Result):
- s.resstate = get_resstate((Result) node);
- slot = get_cs_ResultTupleSlot(
- (CommonState)
- s.resstate);
- break;
-
- case classTag(SeqScan):
- s.scanstate = get_scanstate((Scan) node);
- slot = get_cs_ResultTupleSlot((CommonState)
- s.scanstate);
- break;
-
- case classTag(ScanTemps):
- s.scantempstate = get_scantempState((ScanTemps) node);
- slot = get_cs_ResultTupleSlot((CommonState)
- s.scantempstate);
- break;
-
- case classTag(NestLoop):
- s.nlstate = get_nlstate((NestLoop) node);
- slot = get_cs_ResultTupleSlot((CommonState)
- s.nlstate);
- break;
-
- case classTag(Append):
- {
- AppendState unionstate;
- List unionplans;
- int whichplan;
- Plan subplan;
-
- unionstate = get_unionstate((Append) node);
- unionplans = get_unionplans((Append) node);
- whichplan = get_as_whichplan(unionstate);
-
- subplan = (Plan) nth(whichplan, unionplans);
- slot = NodeGetResultTupleSlot(subplan);
- break;
- }
-
- case classTag(IndexScan):
- s.scanstate = get_scanstate((Scan) node);
- slot = get_cs_ResultTupleSlot((CommonState)
- s.scanstate);
- break;
-
- case classTag(Material):
- s.matstate = get_matstate((Material) node);
- slot = get_css_ScanTupleSlot((CommonScanState)
- s.matstate);
- break;
-
- case classTag(Sort):
- s.sortstate = get_sortstate((Sort) node);
- slot = get_css_ScanTupleSlot((CommonScanState)
- s.sortstate);
- break;
-
- case classTag(Agg):
- s.aggstate = get_aggstate((Agg) node);
- slot = get_cs_ResultTupleSlot((CommonState)
- s.aggstate);
- break;
-
- case classTag(Hash):
- s.hashstate = get_hashstate((Hash) node);
- slot = get_cs_ResultTupleSlot((CommonState)
- s.hashstate);
- break;
-
- case classTag(Unique):
- s.uniquestate = get_uniquestate((Unique) node);
- slot = get_cs_ResultTupleSlot((CommonState)
- s.uniquestate);
- break;
-
- case classTag(MergeJoin):
- s.mergestate = get_mergestate((MergeJoin) node);
- slot = get_cs_ResultTupleSlot((CommonState)
- s.mergestate);
- break;
-
- case classTag(HashJoin):
- s.hashjoinstate = get_hashjoinstate((HashJoin) node);
- slot = get_cs_ResultTupleSlot((CommonState)
- s.hashjoinstate);
- break;
-
- default:
- /* ----------------
- * should never get here
- * ----------------
- */
- elog(DEBUG, "NodeGetResultTupleSlot: node not yet supported: %d ",
- NodeGetTag(node));
-
- return NULL;
- }
- return slot;
- }
-
- /* ----------------------------------------------------------------
- * old lisp support routines
- * ----------------------------------------------------------------
- */
- /* ----------------------------------------------------------------
- * ExecGetTupType
- *
- * this gives you the tuple descriptor for tuples returned
- * by this node. I really wish I could ditch this routine,
- * but since not all nodes store their type info in the same
- * place, we have to do something special for each node type.
- *
- * Soon, the system will have to adapt to deal with changing
- * tuple descriptors as we deal with dynamic tuple types
- * being returned from procedure nodes. Perhaps then this
- * routine can be retired. -cim 6/3/91
- *
- * old comments
- * This routine just gets the type information out of the
- * node's state. If you already have a node's state, you
- * can get this information directly, but this is a useful
- * routine if you want to get the type information from
- * the node's inner or outer subplan easily without having
- * to inspect the subplan.. -cim 10/16/89
- *
- * Assume that for existential nodes, we get the targetlist out
- * of the right node's targetlist
- * ----------------------------------------------------------------
- */
-
- TupleDescriptor
- ExecGetTupType(node)
- Plan node;
- {
- TupleTableSlot slot;
- TupleDescriptor tupType;
-
- if (node == NULL)
- return NULL;
-
- slot = NodeGetResultTupleSlot(node);
- tupType = ExecSlotDescriptor((Pointer) slot);
- return tupType;
- }
-
- TupleDescriptor
- ExecCopyTupType(td, natts)
- TupleDescriptor td;
- int natts;
- {
- TupleDescriptor newTd;
- int i;
-
- newTd = CreateTemplateTupleDesc(natts);
- i = 0;
- while (i < natts)
- {
- newTd->data[i] =
- (AttributeTupleForm)palloc( sizeof(AttributeTupleFormD) );
- bcopy(td->data[i], newTd->data[i], sizeof(AttributeTupleFormD));
- i++;
- }
- return newTd;
- }
-
- ExecTupDescriptor
- ExecGetExecTupDesc(node)
- Plan node;
- {
- TupleTableSlot slot;
- ExecTupDescriptor execTupDesc;
-
- if (node == NULL)
- return NULL;
-
- slot = NodeGetResultTupleSlot(node);
- execTupDesc = ExecSlotExecDescriptor(slot);
- return execTupDesc;
- }
-
- /* ----------------------------------------------------------------
- * ExecTypeFromTL
- *
- * Currently there are about 4 different places where we create
- * TupleDescriptors. They should all be merged, or perhaps
- * be rewritten to call BuildDesc().
- *
- * old comments
- * Forms attribute type info from the target list in the node.
- * It assumes all domains are individually specified in the target list.
- * It fails if the target list contains something like Emp.all
- * which represents all the attributes from EMP relation.
- *
- * Conditions:
- * The inner and outer subtrees should be initialized because it
- * might be necessary to know the type infos of the subtrees.
- * ----------------------------------------------------------------
- */
- /**** xxref:
- * ExecInitIndexScan
- * ExecInitMergeJoin
- * ExecInitNestLoop
- * ExecInitResult
- * ExecInitSeqScan
- ****/
- TupleDescriptor
- ExecTypeFromTL(targetList)
- List targetList;
- {
- List tlcdr;
- TupleDescriptor typeInfo;
- Resdom resdom;
- ObjectId restype;
- int len;
-
- /* ----------------
- * examine targetlist - if empty then return NULL
- * ----------------
- */
- len = ExecTargetListLength(targetList);
-
- if (len == 0)
- return NULL;
-
- /* ----------------
- * allocate a new typeInfo
- * ----------------
- */
- typeInfo = ExecMakeTypeInfo(len);
- if (typeInfo == NULL)
- elog(DEBUG, "ExecTypeFromTL: ExecMakeTypeInfo returns null.");
-
- /* ----------------
- * notes: get resdom from (resdom expr)
- * get_typbyval comes from src/lib/l-lisp/lsyscache.c
- * ----------------
- */
- tlcdr = targetList;
- while (! lispNullp(tlcdr)) {
- if (tl_is_resdom(CAR(tlcdr))) {
- resdom = (Resdom) tl_resdom(CAR(tlcdr));
- restype = get_restype(resdom);
-
- ExecSetTypeInfo((int) get_resno(resdom) - 1, /* index */
- (struct attribute **) typeInfo, /* type info addr */
- (ObjectId) restype, /* type id */
- (int) get_resno(resdom), /* att num */
- (int) get_reslen(resdom), /* att len */
- (char *) get_resname(resdom), /* att name */
- get_typbyval(restype)); /* att by val */
- }
- else {
- Resdom fjRes;
- List fjTlistP;
- List fjList = CAR(tlcdr);
- Fjoin fjNode = (Fjoin)tl_node(fjList);
-
- fjRes = (Resdom)tl_resdom(get_fj_innerNode(fjNode));
- restype = get_restype(fjRes);
-
- ExecSetTypeInfo(
- (int) get_resno(fjRes) - 1, /* index */
- (struct attribute **) typeInfo, /* addr of type info */
- (ObjectId) restype, /* type id */
- (int) get_resno(fjRes), /* att num */
- (int) get_reslen(fjRes), /* att len */
- (char *) get_resname(fjRes), /* att name */
- get_typbyval(restype)); /* att by val */
-
- foreach(fjTlistP, CDR(fjList)) {
- List fjTle = CAR(fjTlistP);
-
- fjRes = (Resdom)tl_resdom(fjTle);
- ExecSetTypeInfo(
- (int) get_resno(fjRes) - 1, /* index */
- (struct attribute **) typeInfo, /* addr of type info */
- (ObjectId) restype, /* type id */
- (int) get_resno(fjRes), /* att num */
- (int) get_reslen(fjRes), /* att len */
- (char *) get_resname(fjRes), /* att name */
- get_typbyval(get_restype(fjRes))); /* att by val */
-
- } /* foreach */
-
- } /* else tl_is_resdom */
-
- tlcdr = CDR(tlcdr);
-
- } /* while (! lispNullp(tlcdr)) */
-
- return typeInfo;
- }
-
- /*
- * function to convert from an ExecTupDescriptor to a flat Tuple Descriptor
- */
- TupleDescriptor
- ExecTupDescToTupDesc(execTupDesc,len)
- ExecTupDescriptor execTupDesc;
- int len;
- {
- int i, j;
- TupleDescriptor tupdesc;
- int tdlen;
- int count;
-
- tdlen = 0;
- for (i=0; i<len; i++)
- tdlen += execTupDesc->data[i]->len;
- tupdesc = CreateTemplateTupleDesc(tdlen);
- count = 0;
- for (i=0; i<len; i++) {
- for (j=0; j<execTupDesc->data[i]->len; j++) {
- tupdesc->data[count] = (AttributeTupleForm)
- palloc(sizeof(AttributeTupleFormD));
- bcopy(execTupDesc->data[i]->attdesc->data[j],
- tupdesc->data[count],
- sizeof(AttributeTupleFormD));
- tupdesc->data[count++]->attcacheoff = -1;
- }
- }
- return tupdesc;
- }
-
- /*
- * function to convert from a Tuple Descriptor to an ExecTupDescriptor
- */
- ExecTupDescriptor
- TupDescToExecTupDesc(tupDesc, len)
- TupleDescriptor tupDesc;
- int len;
- {
- ExecTupDescriptor execTupDesc;
- int i;
-
- execTupDesc = ExecMakeExecTupDesc(len);
- for (i=0; i<len; i++) {
- execTupDesc->data[i] = MakeExecAttDesc(ATTVAL, 1, (TupleDescriptor)tupDesc->data[i]);
- }
- return execTupDesc;
- }
-